package com.mengya.completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @ClassName CompletableFutureAPIDemo
 * @Description CompletableFuture的一些API
 * @Author xiongwei.wu
 * @Date 2022/11/16 16:38
 **/
public class CompletableFutureAPIDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {

    }

    /**
     * 对计算结果进行合并
     */
    private static void m7() {
        System.out.println(CompletableFuture.supplyAsync(() -> {
            return 10;
        }).thenCombine(CompletableFuture.supplyAsync(() -> {
            return 20;
        }), (r1, r2) -> {
            return r1 + r2;
        }).join());

    }

    /**
     * 对计算速度进行选用
     * @throws InterruptedException
     */
    private static void m6() throws InterruptedException {
        System.out.println(CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException exception) {
                exception.printStackTrace();
            }
            return 1;
        }).applyToEither(CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException exception) {
                exception.printStackTrace();
            }
            return 2;
        }), r -> {
            return r;
        }).join());

        TimeUnit.SECONDS.sleep(3);
    }

    private static void m5() {
        CompletableFuture.supplyAsync(() -> {
            return 1;
        }).thenApply(f -> {
            return f + 2;
        }).thenApply(f -> {
            return f + 3;
        }).thenAccept(System.out::println);

        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenRun(() -> {
        }).join());
        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenAccept(string -> {
        }).join());
        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenApply(resultA -> resultA + "resultB").join());
    }

    private static void m4() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,
                20,
                1L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(50),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        long startTime, endTime;
        startTime = System.currentTimeMillis();
        CompletableFuture.runAsync(() -> {
            System.out.println(1);
        }, threadPoolExecutor).thenRun(() -> {
            System.out.println("-----1");
        }).thenRun(() -> {
            System.out.println("-----2");
        }).thenRun(() -> {
            System.out.println("-----3");
        }).thenRun(() -> {
            System.out.println("-----4");
        });
        endTime = System.currentTimeMillis();
        System.out.println("async 耗时：" + (endTime - startTime));

        threadPoolExecutor.shutdown();
    }

    private static void m3() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,
                20,
                1L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(50),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        long startTime, endTime;
        startTime = System.currentTimeMillis();
        System.out.println(CompletableFuture.supplyAsync(() -> {
            return 1;
        }).handleAsync((f, e) -> {
            System.out.println("-----1");
            return f + 2;
        }).handleAsync((f, e) -> {
            System.out.println("-----2");
            return f + 3;
        }).handleAsync((f, e) -> {
            System.out.println("-----3");
            return f + 4;
        }).whenCompleteAsync((v, e) -> {
            if (e == null) {
                System.out.println("complete result: " + v);
            }
        }).exceptionally(throwable -> {
            throwable.printStackTrace();
            return null;
        }).join());
        endTime = System.currentTimeMillis();
        System.out.println("async 耗时：" + (endTime - startTime));

        threadPoolExecutor.shutdown();
    }

    /**
     * 对计算结果进行处理
     */
    private static void m2() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,
                20,
                1L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(50),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

//        System.out.println(CompletableFuture.supplyAsync(() -> {
//            return 1;
//        }).thenApply(f -> {
//            return f + 2;
//        }).thenApply(f -> {
//            return f + 3;
//        }).thenApply(f -> {
//            return f + 4;
//        }).whenComplete((v, e) -> {
//            if (e == null) {
//                System.out.println("complete result: " + v);
//            }
//        }).exceptionally(throwable -> {
//            throwable.printStackTrace();
//            return null;
//        }).join());

        long startTime, endTime;
        startTime = System.currentTimeMillis();
        System.out.println(CompletableFuture.supplyAsync(() -> {
            return 1;
        }).handle((f, e) -> {
            System.out.println("-----1");
            return f + 2;
        }).handle((f, e) -> {
            System.out.println("-----2");
            return f + 3;
        }).handle((f, e) -> {
            System.out.println("-----3");
            return f + 4;
        }).whenComplete((v, e) -> {
            if (e == null) {
                System.out.println("complete result: " + v);
            }
        }).exceptionally(throwable -> {
            throwable.printStackTrace();
            return null;
        }).join());

        endTime = System.currentTimeMillis();
        System.out.println("async 耗时：" + (endTime - startTime));

        threadPoolExecutor.shutdown();
    }

    /**
     * 获取结果和触发计算
     *
     * @throws InterruptedException
     * @throws ExecutionException
     */
    private static void m1() throws InterruptedException, ExecutionException {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,
                20,
                1L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(50),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException exception) {
                exception.printStackTrace();
            }
            return 10;
        }).thenApply(f -> {
            return f + 20;
        }).whenComplete((v, e) -> {
            if (e == null) {
                System.out.println("---------complete result: " + v);
            }
        }).exceptionally(throwable -> {
            throwable.printStackTrace();
            return null;
        });

        System.out.println("------main over");


//        System.out.println(future.get());
//        System.out.println(future.get(2L, TimeUnit.SECONDS));
        System.out.println(future.getNow(99));
        System.out.println(future.complete(999) + " \t " + future.get());


        threadPoolExecutor.shutdown();
    }
}
